unit StdDrawObjects;
interface
uses DiagramLabel, DrawObject;
type
  TDrawLabel = class(TDrawObject)
  private
    FLabel: TDiagramLabel;
    FWidth, FHeight: Double;
  protected
    procedure InternalDraw; override;
    function GetMinX: Double; override;
    function GetMinY: Double; override;
    function GetMaxX: Double; override;
    function GetMaxY: Double; override;
    function InternalTestHit(X, Y: Double): Boolean; override;
    procedure InternalDrop(DX, DY: Double); override;
  public
    property Label_: TDiagramLabel read FLabel;
    constructor Create(ALabel: TDiagramLabel);
  end;

implementation
uses Windows, Math, Graphics, Classes;

{ TDrawLabel }

constructor TDrawLabel.Create(ALabel: TDiagramLabel);
begin
  FLabel := ALabel;
end;

procedure TDrawLabel.InternalDraw;
var
  StartX, StartY, ShiftX, ShiftY: Integer;
var
  i: Integer;
  Strings: TStringList;

begin
  FLabel.Update;

  Canvas.Font.Assign(FLabel.Font);

  Strings := TStringList.Create;
  try
    Strings.Text := FLabel.Caption;
    FWidth := 0;
    FHeight := 0;
    for i := 0 to Pred(Strings.Count) do
    begin
      if FWidth < Canvas.TextWidth(Strings[i]) then
        FWidth := Canvas.TextWidth(Strings[i]);
      FHeight := FHeight + Canvas.TextHeight(Strings[i]);
    end;

    Canvas.Font.Height := Stretch(Canvas.Font.Height, dNone);
    if FLabel.TransparentBkground then
      Canvas.Brush.Style := bsClear;
    StartX := Stretch(GetMinX, daX);
    StartY := Stretch(GetMinY, daY);
    ShiftX := 0;
    ShiftY := Canvas.TextHeight(FLabel.Caption);

    for i := 0 to Pred(Strings.Count) do
    begin
      Canvas.TextOut(StartX, StartY, Strings[i]);
      Inc(StartX, ShiftX);
      Inc(StartY, ShiftY);
    end;
  finally
    Strings.Free;
  end;
end;

procedure TDrawLabel.InternalDrop(DX, DY: Double);
begin
  FLabel.X := FLabel.X + DX;
  FLabel.Y := FLabel.Y + DY;
end;

function TDrawLabel.InternalTestHit(X, Y: Double): Boolean;
begin
  Result := (X > GetMinX) and (X < GetMaxX) and (Y > GetMinY) and (Y < GetMaxY)
end;

function TDrawLabel.GetMaxX: Double;
begin
  Result := FLabel.X;
  case FLabel.HorzAlign of
    haLeft: Result := Result + FWidth;
    haCenter: Result := Result + FWidth / 2;
  end;
end;

function TDrawLabel.GetMaxY: Double;
begin
  Result := FLabel.Y;
  case FLabel.VertAlign of
    vaTop: Result := Result + FHeight;
    vaCenter: Result := Result + FHeight / 2;
  end;
end;

function TDrawLabel.GetMinX: Double;
begin
  Result := FLabel.X;
  case FLabel.HorzAlign of
    haCenter: Result := Result - FWidth / 2;
    haRight: Result := Result - FWidth;
  end;
end;

function TDrawLabel.GetMinY: Double;
begin
  Result := FLabel.Y;
  case FLabel.VertAlign of
    vaCenter: Result := Result - FHeight / 2;
    vaBottom: Result := Result - FHeight;
  end;
end;

end.

